home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 2
/
The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO
/
clang
/
spawno30.zip
/
SPAWNPTH.ASM
< prev
next >
Wrap
Assembly Source File
|
1990-09-05
|
7KB
|
306 lines
NAME spawnpth
TITLE Path search for disk-swapping spawn() by Ralf Brown
PAGE 60,132
;-----------------------------------
; (c) Copyright 1990 Ralf Brown All Rights Reserved
; This code may be redistributed provided that:
; 1) this copyright notice remains intact and any changes are clearly
; marked
; 2) no fee of any kind is charged
;-----------------------------------
; assembler defines:
; __TINY__, __SMALL__, __COMPACT__, __MEDIUM__, __LARGE__
; exactly one of the above must be defined to specify the memory
; model in use
;-----------------------------------
IFDEF __HUGE__
%error Huge model not supported
ENDIF ;__HUGE__
__BSS__ equ 1 ; yes, we are using uninitialized storage
INCLUDE RULES.ASI
Header@ ; set up segment and group definitions
FFBLK struc
?ffb_reserved db 21 dup (?)
?ffb_attr db ?
?ffb_time dw ?
?ffb_date dw ?
?ffb_size dd ?
?ffb_name db 13 dup (?)
FFBLK ends
; bit flags for the extensions which were found
COM_EXT equ 1
EXE_EXT equ 2
USER_EXT equ 4
DSeg@
ExtSym@ _psp,WORD,__CDECL__
ExtSym@ _doserrno,WORD,__CDECL__
DSegEnd@
BSeg@
env dd ?
found_ext db ? ; which extensions have we found?
executable_path db 80 dup (?) ; size of longest legal path+file+NUL
executable_pad db 4 dup (?) ; in case we run over while adding extension
ffb ffblk <>
name_incl_path db ?
BSegEnd@
CSeg@
assume ds:DGROUP
;----------------------------------------------------------------
; static int pascal check_dir(void) ;
; check a single directory for both .COM and .EXE
;----------------------------------------------------------------
Proc@ CHECK_DIR,__PASCAL__
push es
push di
push ds
pop es
assume es:DGROUP
mov found_ext,0 ; haven't found anything yet
mov di,offset DGROUP:executable_path
mov cx,size executable_path
mov al,0
cld
repne scasb
dec di
; now that we have the end of the name, scan backward to check extension
mov bx,di
mov dl,0
ext_scan_loop:
dec di
cmp di,offset DGROUP:executable_path
je had_no_ext
mov al,[di]
cmp al,'.'
jne not_dot
or dl,dl ; have we seen a wildcard?
jne got_dot
or found_ext,USER_EXT ; yes, user specified a particular extension
jmp short got_extension
not_dot:
cmp al,'/'
je had_no_ext
cmp al,'\'
je had_no_ext
cmp al,':'
je had_no_ext
cmp al,'*'
je got_wildcard
cmp al,'?'
jne ext_scan_loop
got_wildcard:
mov dl,1
jmp ext_scan_loop
had_no_ext:
mov di,bx ; back to end of name
mov byte ptr [di],'.' ; append a period
got_dot:
inc di
mov word ptr [di],'*' ; append an asterisk wildcard and NUL
got_extension:
mov ah,2Fh ; get DTA
MSDOS@
assume es:NOTHING
push es ; and store address for later
push bx
mov dx,offset DGROUP:ffb
mov ah,1Ah ; set DTA to findfirst block
MSDOS@
mov ah,4Eh
mov cx,23h ; search for archive,hidden,and read-only
check_dir_loop:
mov dx,offset DGROUP:executable_path
MSDOS@
jc check_no_more
test found_ext,USER_EXT
jnz check_OK
mov bx,offset DGROUP:ffb.?ffb_name
check_found_ext_loop:
mov al,[bx]
inc bx
cmp al,0
je checked_ext
cmp al,'.'
jne check_found_ext_loop
cmp word ptr [bx],'OC'
jne not_com_ext
cmp byte ptr [bx+2],'M'
jne not_com_ext
or found_ext,COM_EXT
jmp short check_successful
not_com_ext:
cmp word ptr [bx],'XE'
jne checked_ext
cmp byte ptr [bx+2],'E'
jne checked_ext
or found_ext,EXE_EXT
checked_ext:
mov ah,4Fh
jmp check_dir_loop
check_no_more:
test found_ext,COM_EXT or EXE_EXT
je check_failed ; neither .COM nor .EXE found
check_successful:
mov word ptr [di],'OC'
mov ax,'M'
test found_ext,COM_EXT
jne check_succeeded
mov word ptr [di],'XE'
mov ax,'E'
check_succeeded:
mov word ptr [di+2],ax
check_OK:
mov bx,dx
jmp short check_dir_done
check_failed:
xor bx,bx
check_dir_done:
pop dx ; get back original DTA
pop ax
push ds
mov ds,ax
mov ah,1Ah
MSDOS@ ; restore DTA
pop ds
pop di
pop es
or bx,bx ; set ZF if failed
ret
EndProc@ CHECK_DIR,__PASCAL__
;----------------------------------------------------------------
; char * pascal __spawn_search(const char *name) ;
; given a program name, search the PATH for it, returning the full pathname
; or NULL if not found
;----------------------------------------------------------------
PubProc@ __SPAWN_SEARCH,__PASCAL__
; parameters
if ldata
@name = dword ptr [bp+2+cPtrSize]
else
@name = word ptr [bp+2+cPtrSize]
endif
; start of subroutine
push bp
mov bp,sp
push es
push di
push si
; set up pointer to environment
mov es,_psp@
mov es,es:[002Ch]
xor di,di
jmp short find_path
find_path_loop:
cmp byte ptr es:[di],0
je found_path
find_path_loop2:
inc di
cmp byte ptr es:[di-1],0
jne find_path_loop2
find_path:
cmp word ptr es:[di],'AP'
jne find_path_loop
cmp word ptr es:[di+2],'HT'
jne find_path_loop
cmp byte ptr es:[di+4],'='
jne find_path_loop
add di,5
found_path:
mov word ptr env+2,es
mov word ptr env,di
mov di,offset DGROUP:executable_path
cld
search_loop:
mov name_incl_path,0
push ds
pop es
assume es:DGROUP
; append @name to executable_path
pushDS_
LDS_ si,@name
copy_cur_loop:
cmp di,offset DGROUP:executable_pad
jae copy_cur_done
lodsb
stosb
cmp al,'/'
je name_has_path
cmp al,'\'
jne name_no_path
name_has_path:
mov name_incl_path,1
name_no_path:
or al,al
jnz copy_cur_loop
copy_cur_done:
popDS_
call check_dir@
jnz search_successful
cmp name_incl_path,0
jne search_failed ; don't look at PATH unless simple filename
les bx,env
cmp byte ptr es:[bx],0
je search_failed
mov di,offset DGROUP:executable_path
dir_copy_loop:
mov al,es:[bx]
or al,al
je dir_copy_done
inc bx
cmp al,';' ; separator for path entries
je dir_copy_done
mov [di],al
inc di
cmp di,offset DGROUP:executable_pad ; make sure we don't overrun buf
jb dir_copy_loop
dir_copy_done:
mov al,[di-1]
cmp al,'/' ; was last char a slash or backslash?
je dir_has_slash
cmp al,'\'
je dir_has_slash
cmp al,':' ; no slash if only drive letter
je dir_has_slash
mov byte ptr [di],'/'
inc di
dir_has_slash:
mov word ptr env,bx
jmp search_loop
search_successful:
mov ax,bx
if ldata
mov dx,ds
endif
jmp short search_done
search_failed:
mov _doserrno@,2 ; file not found
xor ax,ax
if ldata
xor dx,dx
endif
search_done:
pop si
pop di
pop es
pop bp
ret dPtrSize
EndProc@ __SPAWN_SEARCH,__PASCAL__
CSegEnd@
END